﻿#include "zz.h"

#if defined(__QG_H__)

#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

using namespace tpl;

//
qgFpsCamera* fcam;
Vec2 grot(0.0f, 0.0f);
float gscl = 1.0f;

bool _mouse_move(qgSevMouseMove& e)
{
	static Point pt(0, 0);

	Point dt(pt.x - e.x, pt.y - e.y);
	pt.Set(e.x, e.y);

	if (fcam && e.state == QIMM_RIGHT)
		fcam->RefreshAngle(Vec3((float)dt.y, (float)dt.x, 0.0f), 0.005f);
	else if (e.state == QIMM_LEFT)
	{
		grot.x += dt.y * 0.01f;
		grot.y += dt.x * -0.01f;
	}

	return true;
}

int main(void)
{
	k_mesg("\n");

	qgDevice* dev = qgDevice::New("d11", 640, 480, QGSDF_LAYOUT | QGSDF_AUTO /*| QGSDF_INFO*/);

	if (dev)
	{
		dev->Mount("d:\\z");

		qgStub* stub = dev->GetStub();
		stub->AddMouseMoveHandler(qgSevMouseMoveFunc(&_mouse_move));

		//
		qgFreeType* font = qgFreeType::New();

		//
		static qgLayoutElement s_lenm[] =
		{
			{QGDLOU_POSITION, 0, QGDLOT_FLOAT3, 0, 0, },
			{QGDLOU_TEXTURE, 0, QGDLOT_FLOAT2, 0, 0, },
			{QGDLOU_NORMAL, 0, QGDLOT_FLOAT3, 0, 0, },
			{QGDLOU_TANGENT, 0, QGDLOT_FLOAT3, 0, 0, },
			{QGDLOU_BINORMAL, 0, QGDLOT_FLOAT3, 0, 0, },
		};
		static qgLayoutElement s_lewi[] =
		{
			{QGDLOU_POSITION, 0, QGDLOT_FLOAT3, 0, 0, },
			{QGDLOU_TEXTURE, 0, QGDLOT_FLOAT2, 0, 0, },
			{QGDLOU_NORMAL, 0, QGDLOT_FLOAT3, 0, 0, },
			{QGDLOU_TANGENT, 0, QGDLOT_FLOAT3, 0, 0, },
			{QGDLOU_BINORMAL, 0, QGDLOT_FLOAT3, 0, 0, },
			{QGDLOU_INDEX, 0, QGDLOT_FLOAT4, 0, 0, },
			{QGDLOU_WEIGHT, 0, QGDLOT_FLOAT4, 0, 0, },
		};
		qgLayout* lonm = dev->CreateLayout(s_lenm);
		qgLayout* lowi = dev->CreateLayout(s_lewi);

		//
		qgShader* shdnm = dev->CreateShader(NULL);
		shdnm->BindFile(QGSHADER_PS, "ims1_dsnc.hlsl", 0);
		shdnm->BindFile(QGSHADER_VS, "ims1_dsnc.hlsl", 0);
		shdnm->Link();

		qgShader* shdwi = dev->CreateShader(NULL);
		shdwi->BindFile(QGSHADER_PS, "ims1_dsncs.hlsl", 0);
		shdwi->BindFile(QGSHADER_VS, "ims1_dsncs.hlsl", 0);
		shdwi->Link();

		qgSplr* splr = dev->CreateSplr(qgSplrDataEx(QGFLT_MAG_MIN_MIP_LINEAR));

		//
		fcam = qgFpsCamera::New();
		fcam->SetProcessLayout(true);
		fcam->SetMoveSpeed(50.0f);
		fcam->SetLocation(Vec3(0.0f, 150.0f, -380.0f));

		//
		qgSmm* smm = qgSmm::New(0, "imft.smm", 0);

		qgSma* sma = qgSma::New("imft.sma", 0);
		sma->Link(smm);
		sma->TurnLoop(true);
		sma->SetSpeed(-1.0f);

		qgTexture* tdiff = dev->CreateTexture("im_diffuse.png", 0);
		qgTexture* tspec = dev->CreateTexture("im_spec.png", 0);
		qgTexture* tnorm = dev->CreateTexture("im_norm.png", 0);

		kint nmsh = smm->GetMeshCount();
		for (kint i = 0; i < nmsh; i++)
		{
			qgSmmMesh* m = smm->GetMeshNth(i);
			m->SetTexture(0, tdiff);
			m->SetTexture(1, tspec);
			m->SetTexture(2, tnorm);

			if (K_OFLAG(m->GetInsts(), 0x8000))
			{
				m->SetLayout(lowi);
				m->SetShader(shdwi);
			}
			else
			{
				m->SetLayout(lonm);
				m->SetShader(shdnm);
			}
		}

		// 
		bool isanim = false;
		sma->GetUnit()->dur.max = 2.6f;

		//
		while (dev->Run())
		{
			float adv = stub->GetAdvance();

			qgUimKey k;
			stub->GetKeyTable(&k);

			if (k.key[QIK_1]) isanim = true;
			if (k.key[QIK_2]) isanim = false;

			if (k.key[QIK_Q]) grot.y -= KM_PI_HALF * adv;
			if (k.key[QIK_W]) grot.y += KM_PI_HALF * adv;
			if (k.key[QIK_A]) grot.x -= KM_PI_HALF * adv;
			if (k.key[QIK_S]) grot.x += KM_PI_HALF * adv;
			//if (k.key[QIK_1]) gscl -= 5.0f * adv;
			//if (k.key[QIK_2]) gscl += 5.0f * adv;

#if 1
			bool ismove = false;
			if (k.key[QIK_I]) ismove = true, fcam->MoveKey(QSFPSWMV_BACKWARD);
			if (k.key[QIK_K]) ismove = true, fcam->MoveKey(QSFPSWMV_FORWARD);
			if (k.key[QIK_J]) ismove = true, fcam->MoveKey(QSFPSWMV_RIGHT);
			if (k.key[QIK_L]) ismove = true, fcam->MoveKey(QSFPSWMV_LEFT);
			if (k.key[QIK_U]) ismove = true, fcam->MoveKey(QSFPSWMV_UP);
			if (k.key[QIK_O]) ismove = true, fcam->MoveKey(QSFPSWMV_DOWN);

			if (ismove)
				fcam->RefreshMove(adv);
#endif
			fcam->Update(adv);

			if (isanim)
				sma->Update(adv);

			smm->SetLocation(Vec3(0.0f, 0.0f, 0.0f));
			smm->SetRotation(Quat::Rotation(Vec3(grot.x, grot.y + KM_PI, 0.0f)));
			smm->SetScaling(Vec3(gscl, gscl, gscl));
			smm->Update(adv);

			//
			if (dev->Enter())
			{
				dev->SetTM(QGTMS_PROJ, fcam->GetProjTM());
				dev->SetTM(QGTMS_VIEW, fcam->GetViewTM());

				dev->SetSplr(0, splr);
				dev->SetSplr(1, splr);
				dev->SetSplr(2, splr);
				dev->SetSplr(3, splr);

				dev->SetPropVec(0, Vec4(0.0f, 500.0f, -500.0f, 1.0f));
				dev->SetPropVec(1, Vec4(1.0f, 1.0f, 1.0f, 1.0f));
				dev->SetPropVec(2, Vec4(*(Vec3*)&fcam->GetViewTM()._41, 1.0f));
				//dev->SetPropVec(2, Vec4(0.0f, 100.0f, 395.0f, 1.0f));

				//
				smm->Draw();

				//
				dev->SetTexture(0, NULL);
				dev->SetTexture(1, NULL);
				dev->SetTexture(2, NULL);
				dev->SetTexture(3, NULL);

				//
				qgUimMouse m;
				stub->GetMouse(&m);
				Vec3 v = fcam->GetViewPos();

				Vec3 t = fcam->Project(Vec3(0.0f, 0.0f, 0.0f), Metrices::Identity);

				font->WriteFormat(5, 5, 0, "[%.2f] [%d:%d] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]", stub->GetRunFps(),
					m.point.x, m.point.y, v.x, v.y, v.z, t.x, t.y, t.z);


				qgSmaUnit* u = sma->GetUnit();
				font->WriteFormat(5, 30, 0, "[%.2f] %s", u->cur, isanim ? "ANIM" : "STOP");

				dev->Leave();
				dev->Flush();
			}
		}

		//tcube->Unload();
		tnorm->Unload();
		tspec->Unload();
		tdiff->Unload();

		sma->Unload();
		smm->Unload();

		font->Unload();
		dev->Unload();
	}

	return 0;
}

#endif
